package com.velociti.ikarus.widget.client.ui;

import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.i18n.client.NumberFormat;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.UIDL;

public class VIkarusNumericField extends VIkarusTextField {

	private int scaleSize;
	private String decimalSeperator;
	private String groupingSeperator;
	private int precisionSize;
	private boolean useGroupingSeperator;

	public VIkarusNumericField() {
	}

	boolean isUseScale() {
		return scaleSize > 0;
	}

	protected KeyPressHandler getKeyPressHandler() {
		return new KeyPressHandler() {

			public void onKeyPress(KeyPressEvent e) {
				if (keyCodes.contains(e.getNativeEvent().getKeyCode())) {
					if (e.getNativeEvent().getKeyCode() == KeyCodes.KEY_LEFT || e.getNativeEvent().getKeyCode() == KeyCodes.KEY_RIGHT) {
						return;
					} else if (e.getNativeEvent().getKeyCode() == KeyCodes.KEY_BACKSPACE || e.getNativeEvent().getKeyCode() == KeyCodes.KEY_DELETE) {
						StringBuffer text = new StringBuffer(getText());
						int decimalSepIndex = isUseScale() ? text.indexOf(decimalSeperator) : text.length() - 1;
						int cursorPos = getCursorPos();
						String sText = null;
						int nextCursorPos = cursorPos;

						if ((e.getNativeEvent().getKeyCode() == KeyCodes.KEY_BACKSPACE)) {
							if (isUseScale() && cursorPos == decimalSepIndex + 1) {
								cursorPos = cursorPos - 1;
							}

							if (isUseScale() && cursorPos >= decimalSepIndex + 1) {
								// Decimal Part
								text.replace(cursorPos - 1, cursorPos, "");
								nextCursorPos = cursorPos - 1;
								sText = text.toString();
								setValue(sText);
							} else {
								// Integer Part
								int beforeLen = text.length();
								text.replace(cursorPos - 1, cursorPos, "");
								sText = text.toString();
								if (useGroupingSeperator) {
									sText = sText.replaceAll(groupingSeperator, "");
								}
								setValue(sText);
								int afterLen = getText().length();
								nextCursorPos = cursorPos - (beforeLen - afterLen);
							}

						} else {
							if (isUseScale() && cursorPos == decimalSepIndex) {
								cursorPos = cursorPos + 1;
							}
							if (isUseScale() && cursorPos >= decimalSepIndex + 1) {
								// Decimal Part
								text.replace(cursorPos, cursorPos + 1, "");
								nextCursorPos = cursorPos;
								sText = text.toString();
								setValue(sText);
							} else {
								// Integer Part
								if (!isUseScale() && cursorPos >= text.length()) {
									e.preventDefault();
									return;
								}
								int beforeLen = text.length();
								text.replace(cursorPos, cursorPos + 1, "");
								sText = text.toString();
								if (useGroupingSeperator) {
									sText = sText.replaceAll(groupingSeperator, "");
								}
								setValue(sText);
								int afterLen = getText().length();
								nextCursorPos = cursorPos == 0 ? cursorPos : (cursorPos - (beforeLen - (afterLen + 1)));
							}
						}
						setCursorPos(nextCursorPos);
						e.preventDefault();
					}
				} else {
					if (!Character.isDigit(e.getCharCode()) && (!isUseScale() || e.getCharCode() != decimalSeperator.charAt(0))) {
						e.preventDefault();
						return;
					}
					StringBuffer formattedText = new StringBuffer(getText());
					int decimalSepIndex = isUseScale() ? formattedText.indexOf(decimalSeperator) : formattedText.length() - 1;
					int beforeLen = isUseScale() ? formattedText.substring(0, decimalSepIndex).length() : formattedText.length();
					int cursorPos = getCursorPos();
					if (!isUseScale() || cursorPos < decimalSepIndex + 1) {// Integer

						if (isUseScale() && e.getCharCode() == decimalSeperator.charAt(0)) {
							setCursorPos(decimalSepIndex + 1);
							e.preventDefault();
							return;
						}

						formattedText.insert(cursorPos, e.getCharCode());
						setValue(formattedText.toString());
						decimalSepIndex = isUseScale() ? getText().indexOf(decimalSeperator) : formattedText.length() - 1;
						int afterLen = isUseScale() ? getText().substring(0, decimalSepIndex).length() : getText().length();
						setCursorPos(cursorPos + (afterLen - beforeLen));
					} else {// decimal Part
						if (e.getCharCode() == decimalSeperator.charAt(0) || cursorPos == (decimalSepIndex + 1 + scaleSize)) {
							e.preventDefault();
							return;
						}
						formattedText.replace(cursorPos, cursorPos + 1, String.valueOf(e.getCharCode()));
						setValue(formattedText.toString());
						setCursorPos(cursorPos + 1);
					}
					e.preventDefault();
				}
			}
		};
	}

	public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
		super.updateFromUIDL(uidl, client);
		if (client.updateComponent(this, uidl, false)) {
			return;
		}
		decimalSeperator = uidl.getStringAttribute("decimalsep");
		groupingSeperator = uidl.getStringAttribute("groupingsep");
		scaleSize = uidl.getIntAttribute("scale");
		precisionSize = uidl.getIntAttribute("precision");
		useGroupingSeperator = uidl.getBooleanAttribute("usegrouping");
		String alignment = uidl.getStringAttribute("alignment");
		getElement().getStyle().setProperty("textAlign", alignment);

	}

	public void setText(String value) {
		if (value == null || value.trim().length() == 0) {
			value = "0";
		}
		NumberFormat formatter = createFormatter();
		Number number = formatter.parse(value);
		String fString = formatter.format(number);
		super.setText(fString);
	}

	public void onFocus(FocusEvent event) {
		super.onFocus(event);
		int index = 0;
		if (isUseScale()) {
			index = getText().indexOf(decimalSeperator);
		}
		setCursorPos(index);
	}

	private NumberFormat createFormatter() {
		StringBuffer pattern = new StringBuffer();
		if (useGroupingSeperator) {
			pattern.append("###");
			pattern.append(groupingSeperator);
		}
		pattern.append("##0");
		if (isUseScale()) {
			pattern.append(decimalSeperator);
			for (int i = 0; i < scaleSize; i++) {
				pattern.append("0");
			}
		}
		return NumberFormat.getFormat(pattern.toString());
	}

	public String getValue() {
		if (useGroupingSeperator)
			return super.getValue().replaceAll(groupingSeperator, "");
		else
			return super.getValue();
	}

	public String getFormattedValue() {
		return super.getValue();
	}

	public int getScaleSize() {
		return scaleSize;
	}

	public String getGroupingSeperator() {
		return groupingSeperator;
	}
}
